<?php
/**
 * Zendex (Zend (Framework) Extensions)
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://zfx.netatoo.fr/license/new-bsd
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to support@netatoo.fr so we can send you a copy immediately.
 *
 * @category   Zendex
 * @package    Zendex_Bootstrap
 * @copyright  Copyright (c) 2007 Netatoo FR S.A.R.L. (http://www.netatoo.fr)
 * @license    http://Zendex.netatoo.fr/license/new-bsd     New BSD License
 */

/**
 * @see Zendex_Bootstrap
 */
require_once 'Zendex/Bootstrap.php';

/**
 * @see Zendex_Bootstrap_Plugin_Abstract
 */
require_once 'Zendex/Bootstrap/Plugin/Abstract.php';

/**
 * @category   Zendex
 * @package    Zendex_Bootstrap
 * @copyright  Copyright (c) 2007 Netatoo FR S.A.R.L. (http://www.netatoo.fr)
 * @license    http://Zendex.netatoo.fr/license/new-bsd     New BSD License
 */
class Zendex_Bootstrap_Plugin_Broker extends Zendex_Bootstrap_Plugin_Abstract
{

    /**
     * Array of instance of objects extending Zendex_Bootstrap_Plugin_Abstract
     *
     * @var array
     */
    protected $_plugins = array();


    /**
     * Register a plugin.
     *
     * @param  Zendex_Bootstrap_Plugin_Abstract $plugin
     * @return Zendex_Bootstrap_Plugin_Broker
     */
    public function registerPlugin(Zendex_Bootstrap_Plugin_Abstract $plugin, $stackIndex = null)
    {
        if (false !== array_search($plugin, $this->_plugins, true)) {
            throw new Zendex_Bootstrap_Exception('Plugin already registered');
        }

         $stackIndex = (int) $stackIndex;

        if ($stackIndex) {
            if (isset($this->_plugins[$stackIndex])) {
                throw new Zendex_Bootstrap_Exception('Plugin with stackIndex "' . $stackIndex . '" already registered');
            }
            $this->_plugins[$stackIndex] = $plugin;
        } else {
            $stackIndex = count($this->_plugins);
            while (isset($this->_plugins[$stackIndex])) {
                ++$stackIndex;
            }
            $this->_plugins[$stackIndex] = $plugin;
        }
        
        $node = $this->getXmlElement();
        if ($node) {
            $this->_plugins[$stackIndex]->setXmlElement($node);
        }

    }

    /**
     * Is a plugin of a particular class registered?
     *
     * @param  string $class
     * @return bool
     */
    public function hasPlugin($class)
    {
        foreach ($this->_plugins as $plugin) {
            $type = get_class($plugin);
            if ($class == $type) {
                return true;
            }
        }

        return false;
    }

    /**
     * Retrieve a plugin or plugins by class
     *
     * @param  string $class Class name of plugin(s) desired
     * @return false|Zendex_Bootstrap_Plugin_Abstract|array Returns false if 
     * none found, plugin if only one found, and array of plugins if multiple 
     * plugins of same class found
     */
    public function getPlugin($class)
    {
        $found = array();
        foreach ($this->_plugins as $plugin) {
            $type = get_class($plugin);
            if ($class == $type) {
                $found[] = $plugin;
            }
        }

        switch (count($found)) {
            case 0:
                return false;
            case 1:
                return $found[0];
            default:
                return $found;
        }
    }

    /**
     * Retrieve all plugins
     *
     * @return array
     */
    public function getPlugins()
    {
        return $this->_plugins;
    }
    
    /**
     * Set xml element useful for children node, and register with each plugin
     *
     * @param SimpleXMLElement $element
     * @return Zendex_Bootstrap_Plugin_Broker
     */
    public function setXmlElement(SimpleXMLElement $element)
    {
        $this->_xmlElement = $element;

        foreach ($this->_plugins as $plugin) {
            $plugin->setXmlElement($element);
        }

        return $this;
    }

    /**
     * Get xml element useful for children node
     *
     * @return SimpleXMLElement
     */
    public function getXmlElement()
    {
        return $this->_xmlElement;
    }

    /**
     * Called before Zendex_Bootstrap begins 
     * evaluating the xml callback methods.
     *
     * @return void
     */
    public function launchStartup()
    {
        foreach ($this->_plugins as $plugin) {
            try {
                $plugin->launchStartup();
            } catch (Exception $e) {
                throw $e;
            }
        }
    }
    
    /**
     * Called before Zendex_Bootstrap_Parser begins 
     * evaluating the xml callback methods.
     *
     * @param SimpleXMLElement $xml
     * @return void
     */
    public function dispatchLoopStartup(SimpleXMLElement $xml)
    {
        foreach ($this->_plugins as $plugin) {
            try {
                $plugin->dispatchLoopStartup($xml);
            } catch (Exception $e) {
                throw $e;
            }
        }
    }
    
    /**
     * Called before Zendex_Bootstrap_Parser begins 
     * evaluating the xml callback methods.
     *
     * @param string $elemName
     * @param SimpleXMLElement $xml
     * @return void
     */
    public function preDispatchElement($elemName, SimpleXMLElement $xml)
    {
        foreach ($this->_plugins as $plugin) {
            try {
                $plugin->preDispatchElement($elemName, $xml);
            } catch (Exception $e) {
                throw $e;
            }
        }
    }
    
    /**
     * Called before Zendex_Bootstrap_Parser begins 
     * evaluating the xml callback methods.
     *
     * @param string $elemName
     * @param SimpleXMLElement $xml
     * @return void
     */
    public function postDispatchElement($elemName, SimpleXMLElement $xml)
    {
        foreach ($this->_plugins as $plugin) {
            try {
                $plugin->postDispatchElement($elemName, $xml);
            } catch (Exception $e) {
                throw $e;
            }
        }
    }
    
    /**
     * Called after Zendex_Bootstrap_Parser has finish 
     * evaluating the xml callback methods.
     *
     * @param SimpleXMLElement $xml
     * @return void
     */
    public function dispatchLoopShutdown(SimpleXMLElement $xml)
    {
        foreach ($this->_plugins as $plugin) {
            try {
                $plugin->dispatchLoopShutdown($xml);
            } catch (Exception $e) {
                throw $e;
            }
        }
    }
}
